/**
 * Created by perqin on 16-12-4.
 */

var util = require('util'),
  Strategy = require('passport-strategy').Strategy;

function MultiStrategy(options, sendCode, findOrCreateUser) {
  options = options || {};

  Strategy.call(this);
  this.name = 'multi';
  this.bits = options.bits || 6;
  this.trialIdBits = options.trialIdBits || 8;
  this.expired = options.expired || (15 * 60 * 1000);
  this.sendCode = sendCode;
  this.findOrCreateUser = findOrCreateUser;
}

util.inherits(MultiStrategy, Strategy);

MultiStrategy.prototype.authenticate = function (req, options) {
  var self = this;
  var code;
  req.session.multi = req.session.multi || {};
  // Directly signin
  if (req.body.type === 'trial') {
    code = randomCode(self.trialIdBits);
    return self.findOrCreateUser(code, function (err, user) {
      if (err) return self.error(err);
      if (!user) return self.fail('Failed to create trial user', 400);
      self.success(user);
    });
  }
  // send sms code
  if (req.body.type === 'sms') {
    code = randomCode(self.bits);
    return self.sendCode(req.body.phone, code, function (err) {
      if (err) {
        return self.error(err);
      }
      // Store code and set 'user' to 'true'
      req.session.multi.code = code;
      req.session.multi.expired = Date.now() + self.expired;
      self.success(true);
    });
  }
  // verify sms code
  if (req.body.type === 'sms_code') {
    if (req.session.multi.code && req.body.code === req.session.multi.code) {
      return self.findOrCreateUser(req.body.phone, function (err, user) {
        if (err) {
          return self.error(err);
        }
        if (!user) {
          return self.fail('User not exists', 400);
        }
        // User created
        self.success(user);
      });
    }
    return self.fail('Invalid SMS code', 401);
  }
  // Fail other types
  self.fail('Unknown type', 400);
};

function randomCode(bit) {
  var code = '';
  for (var i = 0; i < bit; ++i) {
    code = code + Math.floor(Math.random() * 10);
  }
  return code;
}

module.exports.Strategy = MultiStrategy;
